#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <head.h>

// operae 1-登录  2-查询单次  3-退出 4-注册
typedef struct msg {
    int operae;
    char user_name[100];
    char passwd[100];
    int log_fla;
    char key_1[100];
    char msg_masse[500];
    char user_name_reg[100];
    char passwd_reg[100];
    int reg_fla;
} msg_t;

#define MAXLINE 10   //最大长度
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 8888
#define INFTIM 1000
#define IP_ADDR "192.168.250.100"



static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
    int i;
    for (i = 0; i < argc; i++) {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}
int log_in(
        char *name_text_log, char *passwd,
        int log_stat, char *name_text, char *msg_masse_main) {
    if (log_stat == 1) {
        printf("您已经登录无需重复登录\n");
        return -1;
    }
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }

    sprintf(buff, "select  passwd from  user_reg where  name_text='%s' ", name_text_log);

    sql = buff;

    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("用户名错误 ::%s  没有这个用户...\n", name_text_log);
        strcpy(msg_masse_main, "用户名错误  没有这个用户");
        sqlite3_close(db);
        return -1;
    }
    int res = strcmp(dbResult[1], passwd);
    if (res == 0) {
        strcpy(name_text, name_text_log);
        log_stat = 1;
        sqlite3_close(db);
        printf("log_in success...\n");
        strcpy(msg_masse_main, "log_in success");
        return 0;
    } else {
        printf("passwd error...\n");
        strcpy(msg_masse_main, "passwd error");
        sqlite3_close(db);
        return -1;
    }
}

int insert_his(char *name_text ,char *key_1) {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    char buff[100] = {0};

    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    sprintf(buff, "INSERT INTO user_did_his (name_text,key_1) VALUES ('%s','%s'); ", name_text, key_1);
    sql = buff;
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "username  register SQL error: \n");
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
        return -1;
    } else {
        sqlite3_close(db);
        return 0;
    }
}

int do_serch(char * user_name,char *key_1, char *msg_masse_main) {
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg, *buff_p, *buff_p_1;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }

    sprintf(buff, "select  trans from  dict_1 where  key_='%s'", key_1);
    sql = buff;
    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("单词 ::%s  没有这个单词...\n", key_1);
        sprintf(msg_masse_main, "单词 ::%s  没有这个单词...\n", key_1);
        sqlite3_close(db);
        return -1;
    }
    memset(buff, 0, sizeof(buff));
    //遍历结果 将开始的空格去掉
    for (int i = 0; i < strlen(dbResult[1]); i++) {
        if (dbResult[1][i] == 32) {}
        else {
            buff_p = &dbResult[1][i];
            break;
        }
    }
    insert_his(user_name,key_1);
    printf("%s---%s", key_1, buff_p);
    sprintf(msg_masse_main, "%s---%s", key_1, buff_p);
    return 0;
}

int reg_ins_sql(char *name, char *passwd,char * msg_masse_main) {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    char buff[100] = {0};

    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    // "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "
    // "VALUES (5, 'Paul', 32, 'California', 20000.00 ); "
    sprintf(buff, "INSERT INTO user_reg (name_text,passwd) VALUES ('%s','%s'); ", name, passwd);
    sql = buff;
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

    if (rc != SQLITE_OK) {
        fprintf(stderr, "username %s register SQL error: %s\n", name, zErrMsg);
        sprintf(msg_masse_main, "username %s register SQL error: %s\n", name, zErrMsg);
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
        return -1;
    } else {
        fprintf(stdout, "user ::%s register success\n", name);
        sprintf(msg_masse_main, "user ::%s register success\n", name);
        sqlite3_close(db);
        return 0;
    }
}

int select_hsi(char * name_text,char * msg_masse_main) {
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg, *buff_p, *buff_p_1;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    sprintf(buff, "select  key_1 from  user_did_his where  name_text='%s'", name_text);
    sql = buff;
    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("用户::%s  没有这个查询...\n",name_text);
        sprintf(msg_masse_main, "用户::%s  没有这个查询...\n",name_text);
        sqlite3_close(db);
        return -1;
    }
    char msg_temp[100]={0};
    printf("用户::%s 共查询了 %d 次\n", name_text, nRow);
    sprintf(msg_masse_main, "用户::%s 共查询了 %d 次\n", name_text, nRow);
    for (int i = 1; i <= nRow; i++) {
        memset(msg_temp,0,100);
        for (int j = 0; j < nColumn; j++) {
            printf("%-5s\t", dbResult[i * nColumn + j]);
            sprintf(msg_temp, "%-5s\t", dbResult[i * nColumn + j]);
        }
        if (i % 5 == 0) { printf("\n");
            strcat(msg_temp,"\n");}
        strcat(msg_masse_main,msg_temp);
    }
    printf("\n");
    printf("用户::%s 共查询了 %d 次\n", name_text, nRow);
    // user_did_his
    return 0;
}

int main() {
    int nfds;
    struct epoll_event ev, events[5];
    struct sockaddr_in clientaddr, serveraddr;
    int epfd;
    int listenfd;//监听fd
    int maxi;
    int i;
    int sock_fd, conn_fd;
    char buf[MAXLINE];

    epfd = epoll_create(256);//生成epoll句柄
    listenfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字
    ev.data.fd = listenfd;//设置与要处理事件相关的文件描述符
    ev.events = EPOLLIN;//设置要处理的事件类型

    epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);//注册epoll事件

    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(SERV_PORT);
    bind(listenfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr));//绑定套接口
    socklen_t clilen;
    listen(listenfd, LISTENQ);//转为监听套接字



    int n;
    while (1) {
        nfds = epoll_wait(epfd, events, 5, 500);

        //等待事件发生  参数解析  epfd events 事件  5 支持同时处理事件个数  time_out 等待时间
        //处理所发生的所有事件
        for (i = 0; i < nfds; i++) {
            if (events[i].data.fd == listenfd)
                //有新的连接
            {
                clilen = sizeof(struct sockaddr_in);
                conn_fd = accept(
                        listenfd,
                        (struct sockaddr *) &clientaddr,
                        &clilen);
                printf("accept a new client : %s\n", inet_ntoa(clientaddr.sin_addr));
                ev.data.fd = conn_fd;
                ev.events = EPOLLIN;//设置监听事件为可读
                epoll_ctl(epfd, EPOLL_CTL_ADD, conn_fd, &ev);//新增套接字
            } else if (events[i].events & EPOLLIN)
                //可读事件
            {
                if ((sock_fd = events[i].data.fd) < 0)
                    continue;
                if ((n = recv(sock_fd, buf, MAXLINE, 0)) < 0) {
                    if (errno == ECONNRESET) {
                        close(sock_fd);
                        events[i].data.fd = -1;
                    } else {
                        printf("readline error\n");
                    }
                } else if (n == 0) {
                    close(sock_fd);
                    printf("关闭\n");
                    events[i].data.fd = -1;
                }
                printf("%d -- > %s\n", sock_fd, buf);
                ev.data.fd = sock_fd;
                ev.events = EPOLLOUT;//修改监听事件为可写
                epoll_ctl(epfd, EPOLL_CTL_MOD, sock_fd, &ev);
            } else if (events[i].events & EPOLLOUT)
                //可写事件
            {
                sock_fd = events[i].data.fd;
                printf("OUT\n");
                // scanf("%s",buf);
                send(sock_fd, "i am epoll", MAXLINE, 0);
                ev.data.fd = sock_fd;
                ev.events = EPOLLIN;
                epoll_ctl(epfd, EPOLL_CTL_MOD, sock_fd, &ev);
            }
        }
    }
    return 0;
}